/**
 * Copyright (c) 2010-2011 Pierre Labatut
 *
 * This file is part of Space-Chronicles project.
 *
 * Space-Chronicles is free software: you can redistribute it and/or modify it
 * under the terms of its license which may be found in the accompanying
 * LICENSE file or <http://code.google.com/p/space-chronicles/>.
 */
package space.app.common;

import java.awt.event.WindowEvent;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import space.debug.DbgError;

/**
 *
 * @author Pierre
 */
public class Application<Message> {

    static final Logger logger = Logger.getLogger(Application.class.getName());
    private final ServerFrame<Message> frame;
    final LocationHandler locationHandler;
    private final Server<Message> server;
    private Options options;

    static public <Message> void run(final ApplicationBuilder<Message> builder) {
        if (builder == null) {
            throw new NullPointerException();
        }
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                Application application = new Application(builder);
                application.run();
            }
        });
    }

    public static void initialization() {
        setupErrorHandler();
        setupLog();
        setupLookAndFeel();
    }

    private Application(ApplicationBuilder<Message> builder) {
        initialization();

        if (builder == null) {
            throw new NullPointerException();
        }


        frame = builder.createFrame(this);
        locationHandler = new LocationHandler(frame);
        locationHandler.load();
        server = builder.createServer(this);
        options = Options.readPreferences(preferenceNode());
    }

    public void showOptions() {
        final Options newPref = options.showDialog(frame);
        if (newPref != null) {
            options = newPref;
            frame.onOptionChange(options);
            server.onOptionChange(options);
        }
    }

    /**
     * @param args
     * <ul>
     * <li>no args</li>
     * <li>-open "filepath"</li>
     * <ul>
     */
    public static void main(String args[]) {
    }

    static void setupErrorHandler() {
        Thread.setDefaultUncaughtExceptionHandler(DbgError.handler());
    }

    static void setupLog() {
        Logger.getLogger("").setLevel(Level.FINEST);
        Logger.getLogger("").addHandler(new ConsoleHandler());
    }

    static void setupLookAndFeel() {

        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(Application.class.getName()).log(Level.SEVERE,
                    null,                    ex);
        }
    }

    void startServer() {
        options.startServer(server);
    }

    public Preferences preferenceNode() {
        return Preferences.userNodeForPackage(getClass());
    }

    void stopServer() {
        server.stop();
    }

    void exit() {
        frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
    }

    void onServerStatus(String string) {
        frame.onServerStatus(string);
    }

    public void onServerStop(String message) {
        frame.onServerStop(message);
    }

    public void onServerRecieved(Message scene) {
        frame.onServerRecieved(scene);
    }

    public void onServerRecieve(String message) {
        frame.onServerRecieve(message);
    }

    public void onServerStart(String message) {
        frame.onServerStart(message);
    }

    public void onServerCrash(String message) {
        frame.onServerCrash(message);
    }

    private void run() {
        frame.setVisible(true);
    }

    

}
